/*
 * TestThread.java
 *
 * Created on September 30, 2002, 2:57 PM
 */

package redman;

import java.lang.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.text.*;
import org.apache.log4j.*;

/**
 *
 * @author  llaranje
 * @version 1
 */
public class TestThread extends Thread {
    
    long period;
    AppMonitor app;
    CompMon comp;
    CompMon.SubCompMon subcomp;
    String objname = null;
    String request = null;
    String expectedresponse = null;
    String response = null;
    String path = null;
    String testname = null;
    PrintWriter out = null;
    
    boolean ping = false;
    
    boolean exit = false;
    
    private static Category trace = Category.getInstance(TestThread.class);
    
    public void terminate() {
        trace.info("Exit condition for TestThread being set to TRUE");
        exit = true;
    }

    /** Creates new Test */
    public TestThread(String objname, String testname, AppMonitor app,       
                                                 CompMon comp, CompMon.SubCompMon subcomp) {
        this.comp = comp;
        this.subcomp = subcomp;
        this.app = app;
        this.objname = objname;
        this.testname = testname;
        
        String stperiod = app.appstatictable.getProperty(objname + "_TEST_" + testname + "_PERIOD");
        
        if (stperiod == null) {
            trace.debug("Could not find period for test " + objname + "_TEST_" + testname
                                                           + " in the application config file");
            return;
        }
        else {
            stperiod = stperiod.trim();
            try {
                period = Integer.parseInt(stperiod);
            }
            catch (Exception e) {
                trace.error("Invalid period ('" + stperiod + "') specified for test " 
                                                          + objname + "_TEST_" + testname);
                return;
            }
        }
        
        trace.debug("Got period for test " + objname + "_TEST_" + testname + ": period = " + stperiod);
       
        if (testname.startsWith("PING"))  {
            request = "TEST " + testname;
            ping = true;
            expectedresponse = "TESTACK";
            trace.debug("Will run TestThread for test " + objname + "_TEST_" + testname);
            start();
        }
        else {
            path = app.appstatictable.getProperty(objname + "_TEST_" + testname + "_PATH");
            if (path != null) {
                path = path.trim();
                
                try {
                    Process p = Runtime.getRuntime().exec(app.homedir + "/" + path);
                }
                catch (IOException e) {
                    trace.error("Failed to execute test path " + app.homedir + "/" + path);
                    return;
                }
            }
        }            
    }

    public void sendTestResponse(String resp) {
        response = resp;
    }
        
    public void run() {      // TestThread
        if (subcomp == null) out = comp.out;
        else out = subcomp.out;
        
        for (;;) {
            response = "     ";
            try {
                out.println(request);
                out.flush();
            }
            catch (Exception e) {
                trace.debug("Exception sending test request '" + request + "': " + e.getMessage());
                continue;
            }
                
            trace.debug("Test request '" + request + "' was successfully sent - Will wait for response");
            
            try {
                sleep(period);
                if (exit) {
                    trace.debug("TestThread for test " + objname + "_TEST_" + testname 
                                                       + " exit status is true - exiting ...");
                    break;
                }
            }
            catch (InterruptedException e) {
                trace.warn("TestThread " + objname + " sleep was interrupted");
            }
            
            if (!response.equals(expectedresponse)) {
                trace.debug("Response from test = '" + response + "' -- Expected response = '" 
                                                                + expectedresponse + "'");
                if (subcomp == null) {
                    trace.error("Hung component " + app.name + ":" + comp.name 
                                                 + " will be killed (did not respond to ping)");
                    comp.killPid(comp.comppid);
                }
                else  {
                    trace.info("Hung subcomponent " + app.name + ":" + comp.name + ":" 
                                      + subcomp.pname + " will be killed (did not respond to ping)");
                    comp.killPid(subcomp.subcomppid);
                }
                trace.debug("TestThread for test " + objname + "_TEST_" + testname 
                                                   + " exiting after killing component ...");
                break;
            }
            else trace.debug("TestThread expected response received. Will send another test request msg.");
        }
        trace.debug("TestThread for test " + objname + "_TEST_" + testname + " exiting ...");
    }
}